package org.cybzacg.convert.converters.numeric;

import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.exception.ConversionException;

/**
 * 抽象数值转换器基类
 * 
 * <p>
 * 提供所有数值类型转换器的公共实现，避免代码重复。
 * 所有数值转换器（Integer、Long、Double等）都应继承此类。
 * 
 * <p>
 * 设计思路：
 * <ul>
 * <li>复用 NumberConverter 的转换逻辑，避免重复代码</li>
 * <li>子类只需指定目标类型，无需实现具体转换逻辑</li>
 * <li>统一的错误处理和日志记录</li>
 * </ul>
 * 
 * <p>
 * 示例用法：
 * 
 * <pre>{@code
 * public class IntegerConverter extends AbstractNumericConverter<Integer> {
 *     public IntegerConverter() {
 *         super(Integer.class, ConversionType.INTEGER);
 *     }
 * }
 * }</pre>
 *
 * @param <T> 目标数值类型
 * @author cybzacg.blog
 * @version 4.0
 * @since 4.0
 */
@Slf4j
public abstract class AbstractNumericConverter<T extends Number> extends AbstractTypeConverter {

    /**
     * 目标数值类型
     */
    private final Class<T> targetClass;

    /**
     * 内部使用的通用数值转换器
     */
    private static final NumberConverter NUMBER_CONVERTER = new NumberConverter();

    /**
     * 构造函数
     *
     * @param targetClass 目标数值类型
     * @param priority    转换器优先级
     */
    protected AbstractNumericConverter(Class<T> targetClass, ConversionPriority priority) {
        super(priority);
        this.targetClass = targetClass;
        log.debug("{} 初始化完成，优先级: {}", getClass().getSimpleName(), priority);
    }

    /**
     * 构造函数（使用默认优先级 HIGH）
     *
     * @param targetClass 目标数值类型
     */
    protected AbstractNumericConverter(Class<T> targetClass) {
        this(targetClass, ConversionPriority.HIGH);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected <R> R doConvert(Object source, Class<R> targetType, R defaultValue, ConversionContext context)
            throws Exception {

        log.debug("开始{}转换: 源类型={}, 目标类型={}, 默认值={}",
                targetClass.getSimpleName(),
                source != null ? source.getClass().getSimpleName() : "null",
                targetType.getSimpleName(),
                defaultValue);

        // 空值处理
        if (source == null) {
            log.debug("源对象为null，返回默认值: {}", defaultValue);
            return defaultValue;
        }

        // 类型已匹配，直接返回
        if (targetType.isInstance(source)) {
            log.debug("源对象已经是目标类型，直接返回: {}", source);
            return (R) source;
        }

        try {
            // 步骤1：将源对象转换为Number（委托给NumberConverter）
            Number number = NUMBER_CONVERTER.convertToNumber(source, context);
            if (number == null) {
                log.debug("转换为Number失败，返回默认值: {}", defaultValue);
                return defaultValue;
            }

            // 步骤2：将Number转换为目标类型（委托给NumberConverter）
            R result = NUMBER_CONVERTER.convertNumberToTargetType(number, targetType, defaultValue, context);

            // 步骤3：范围验证（子类可重写）
            validateRange(number, result, context);

            log.debug("{}转换完成: {} -> {}", targetClass.getSimpleName(), source, result);
            return result;

        } catch (Exception e) {
            log.error("{}转换失败: {} -> {}", targetClass.getSimpleName(), source, targetType, e);
            throw new ConversionException(ConversionError.CONVERSION_FAILED,
                    targetClass.getSimpleName() + "转换失败: " + source + " -> " + targetType, e);
        }
    }

    /**
     * 范围验证
     * 
     * <p>
     * 子类可以重写此方法实现特定类型的范围验证
     * 例如：Integer需要验证是否在Integer.MIN_VALUE和Integer.MAX_VALUE之间
     *
     * @param sourceNumber 源数值
     * @param result       转换结果
     * @param context      转换上下文
     * @throws ConversionException 如果数值超出范围
     */
    protected void validateRange(Number sourceNumber, Object result, ConversionContext context)
            throws ConversionException {
        // 默认不做范围验证，子类可以重写
    }

    @Override
    public Class<?> getSupportedType() {
        return targetClass;
    }

    @Override
    public boolean supports(Class<?> type) {
        // 支持目标类型及其包装/基本类型
        if (targetClass.equals(type)) {
            return true;
        }

        // 处理基本类型和包装类型的对应关系
        return isPrimitiveOrWrapper(targetClass, type);
    }

    /**
     * 检查是否为基本类型和包装类型的对应关系
     *
     * @param wrapperClass   包装类型
     * @param primitiveClass 可能的基本类型
     * @return 是否匹配
     */
    private boolean isPrimitiveOrWrapper(Class<?> wrapperClass, Class<?> primitiveClass) {
        if (wrapperClass == Integer.class && primitiveClass == int.class)
            return true;
        if (wrapperClass == Long.class && primitiveClass == long.class)
            return true;
        if (wrapperClass == Double.class && primitiveClass == double.class)
            return true;
        if (wrapperClass == Float.class && primitiveClass == float.class)
            return true;
        if (wrapperClass == Short.class && primitiveClass == short.class)
            return true;
        if (wrapperClass == Byte.class && primitiveClass == byte.class)
            return true;
        return false;
    }

    @Override
    public String getName() {
        return targetClass.getSimpleName() + "Converter";
    }
}
